package br.com.basili.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.basili.hibernateUtil.ConexaoHibernate;

//TODO: Colocar filtros de Ativo em todas as listas das classes de dominio
public abstract class GenericDAO<T> extends BaseDAO {

	protected Session s;
	protected Transaction tr;
	protected Query q;
	

	protected Session getSession() {
		return ConexaoHibernate.sessionFactory.getCurrentSession();
	}

	protected void beginTransaction() {
		getSession().beginTransaction();
	}

	protected void commit() {
		getSession().getTransaction().commit();
	}

	protected void rollback() {
		getSession().getTransaction().rollback();
	}

	protected void commitAndClose() {
		commit();
		getSession().close();
	}

	protected void rollbackAndClose() {
		rollback();
		getSession().close();
	}

	public void salvar(T baseModel) throws Exception {
		s = ConexaoHibernate.sessionFactory.openSession();
		tr = null;
		
		try {
			tr = s.beginTransaction();
			s.save(baseModel);
			s.flush();
			tr.commit();
			s.clear();
			
		} catch (Exception e) {
			e.printStackTrace();
			tr.rollback();
		}finally{
			s.close();
		}
		
	}
	
	public void editar(T baseModel) throws Exception {
		s = ConexaoHibernate.sessionFactory.openSession();
		tr = null;
		
		try {
			tr = s.beginTransaction();
			s.merge(baseModel);
			tr.commit();
			s.clear();
			
		} catch (Exception e) {
			e.printStackTrace();
			tr.rollback();
		}finally{
			s.close();
		}
		
	}

	public void excluir(T baseModel) throws Exception {
		
		tr = null;
		try {
			
			s = ConexaoHibernate.sessionFactory.openSession();
			tr = s.beginTransaction();
			
				s.delete(baseModel);
				s.flush();
				tr.commit();
				s.clear();
			
			
		} catch (Exception e) {
			e.printStackTrace();
			tr.rollback();
		} finally{
			s.close();
		}
	}

	@SuppressWarnings("unchecked")
	protected List<T> getListaModel(String query, Object... parametros) throws Exception{
		tr = null;
		s = ConexaoHibernate.sessionFactory.openSession();
		List<T> listaT = null;
		
		try {
			tr = s.beginTransaction();
			
			Query q = s.createQuery(query);
			for (int i = 0; i < parametros.length; i++) {
				q.setParameter(i, parametros[i]);
			}
			listaT = (List<T>) q.list();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return listaT;
	}

	@SuppressWarnings("unchecked")
	protected T getSimplesModel(String query, Object... parametros) throws Exception{

		s = ConexaoHibernate.sessionFactory.openSession();
		tr = null;
		T t = null;
		
		try {
			tr = s.beginTransaction();
			Query qs = s.createQuery(query);
			for (int i = 0; i < parametros.length; i++) {
				qs.setParameter(i, parametros[i]);
			}
			t = (T) qs.uniqueResult();
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	protected T getPorCodigo(Integer codigo) throws Exception {
		
		s = ConexaoHibernate.sessionFactory.openSession();
		tr = null;
		T t = null;
		
		try {
			tr = s.beginTransaction();
			final ParameterizedType genericTipo = (ParameterizedType) getClass().getGenericSuperclass();
			Class<T> genericClass = (Class<T>) (genericTipo).getActualTypeArguments()[0];
			t = (T) s.get(genericClass, codigo);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

	void alterarSenha(T baseModel) throws Exception {
		
		s = ConexaoHibernate.sessionFactory.openSession();
		tr = null;
		
		try {
			tr = s.beginTransaction();
			s.saveOrUpdate(baseModel);
			s.flush();
			tr.commit();
			s.clear();
		} catch (Exception e) {
			e.printStackTrace();
			tr.rollback();
		} finally {
			ConexaoHibernate.getInstance().close();
		}
	}
}
